<?php
/**
 * ws 优化 基础类库
 * User: singwa
 * Date: 18/3/2
 * Time: 上午12:34
 */

class Ws {

    CONST HOST = "0.0.0.0";
    CONST PORT = 8812;
    CONST CHARPORT = 8813;

    public $ws = null;
    public $redis = null;
    public function __construct() {

        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        // 增加一个监听端口，用于另外一个聊天室功能的开发
        $this->ws->listen(self::HOST, self::CHARPORT, SWOOLE_SOCK_TCP);

        $this->ws->set(
            [
                'enable_static_handler' => true,
                // 'document_root' => "/mnt/hgfs/D/www/swoole_tp_s/public/static",
                'document_root' => "/Users/wenqing/www/swoole_tp_s/public/static",
                'worker_num' => 2,
                'task_worker_num' => 2,
                'task_enable_coroutine' => true,
                'open_http_protocol' => true,
                'open_websocket_protocol' => true
            ]
        );

        // $t  his->ws->on('request', [$this, 'onRequest']);
        $this->ws->on('workerstart', [$this, 'onWorkerStart']);
        $this->ws->on("open", [$this, 'onOpen']);
        $this->ws->on('request', [$this, 'onRequest']);
        $this->ws->on("message", [$this, 'onMessage']);
        $this->ws->on("task", [$this, 'onTaskGo']);
        $this->ws->on("finish", [$this, 'onFinish']);
        $this->ws->on("close", [$this, 'onClose']);

        echo "con------".PHP_EOL;
//        go(function (){
//            $redis = new Swoole\Coroutine\Redis();
//            $redis->connect('127.0.0.1', 6379);
//            $redis->del('client');
//            echo 'del redis key'.PHP_EOL;
//        });
//        $redis = new Swoole\Coroutine\Redis();
//        $redis->connect('127.0.0.1', 6379);
//        $redis->del('client');
//        echo 'del redis key'.PHP_EOL;

        $this->ws->start();
    }

    /**
     * @param swoole_server $server
     * @param $worker_id
     */
    public function onWorkerStart(swoole_server $server, $worker_id){
        // 加载基础文件
        require __DIR__ . '/../thinkphp/base.php';

        // 删除一下以前的redis信息
//        go(function(){
//            $redis = new Swoole\Coroutine\Redis();
//            $redis->connect('127.0.0.1', 6379);
//            $redis->del('client');
//            echo 'del redis key'.PHP_EOL;
//        });
    }

    /**
     * @param $request
     * @param $response
     */
    public function onRequest($request, $response){
        // 设置全局变量
        // $_SERVER = [];
        if(isset($request->server)){
            foreach ($request->server as $k => $v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }
        if(isset($request->header)){
            foreach ($request->header as $k => $v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }

        $_GET = [];
        if(isset($request->get)){
            foreach ($request->get as $k => $v){
                $_GET[strtolower($k)] = $v;
            }
        }
        $_POST = [];
        if(isset($request->post)){
            foreach ($request->post as $k => $v){
                $_POST[strtolower($k)] = $v;
            }
        }
        // print_r($request->server);
        $_POST['http_server'] = $this->ws;
        // var_dump($_POST['http_server']);
        //$this->http->task(['test' => '123']);
        $_FILES = [];
        if(isset($request->files)){
            foreach ($request->files as $k => $v){
                $_FILES[$k] = $v;
            }
        }

        ob_start();
        // 执行应用并响应
        try{
            \think\Container::get('app')->run()->send();
        }catch (Exception $exception){
            echo $exception->getMessage();
        }
        //echo PHP_EOL."action = ".(request()->action()).PHP_EOL;

        $res = ob_get_contents();
        ob_end_clean();

        // 输出缓冲区内容
        $response->end($res);
    }

    /**
     * 监听ws连接事件
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request) {
        // $clients = \think\facade\Cache::get('clients');
        // $clients[] = $request->fd;
        //var_dump($ws);
        $redis = new Swoole\Coroutine\Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->sAdd('client', $request->fd);
    }

    /**
     * 监听ws消息事件
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame) {

    }

    /**
     * @param $serv
     * @param $taskId
     * @param $workerId
     * @param $data
     */
    public function onTask($serv, $taskId, $workerId, $data) {
        // 根据传递的method分发不同的任务
        switch ($data['method']){
            case 'send':
                cache('code'.$data['code'], $data['phone']);
                break;
            case 'push':
//                go(function () use ($data) {
//                    $redis = new Swoole\Coroutine\Redis();
//                    $redis->connect('127.0.0.1', '6379');
//                    $clients = $redis->sMembers('client');
//                    foreach ($clients as $c){
//                        $_POST['http_server']->push($c, json_encode($data['data']));
//                    }
//                });

                break;
            default:

        }
        echo "task_id = ".$taskId.PHP_EOL;

        return "task work finish";
    }

    public function onTaskGo($serv,  $task){
        $redis = new Swoole\Coroutine\Redis();
        $redis->connect('127.0.0.1', '6379');
        $clients = $redis->sMembers('client');
        $data = ($task->data)['data'];
        foreach ($clients as $c){
            $this->ws->push($c, json_encode($data));
        }
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $data
     */
    public function onFinish($serv, $taskId, $data) {
        echo "taskId:{$taskId}\n";
        echo "finish-data-sucess:{$data}\n";
    }

    /**
     * close
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd) {
        echo "clientid:{$fd}\n";

        $redis = new Swoole\Coroutine\Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->sRem('client', $fd);
    }

    /**
     * 主进程 用于平滑重启的时候使用的
     */
    public function onStart(){
        swoole_set_process_name('live_master');
    }
}

$obj = new Ws();